/**
 * 
 */
package nus.mtech.presentation;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.Date;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.border.EtchedBorder;

import nus.mtech.ApplicationFacade;
import nus.mtech.constant.PresentationConstant;
import nus.mtech.subscription.CableTV;
import nus.mtech.subscription.CableTVChannel;
import nus.mtech.subscription.Subscription;
import nus.mtech.util.DateUtil;
import nus.mtech.util.StringUtil;

import javax.swing.JComboBox;

/**
 * @author Alvin Lee, Jiang Hao Min
 * 
 */
final class CableTVPanel extends JPanel implements ActionListener {

	private static final long serialVersionUID = 3792677426665934781L;
	private static volatile CableTVPanel INSTANCE;
	private JButton btnClear;
	private JButton btnUpdate;
	private JButton btnSearch;
	private JButton btnTransfer;
	private JComboBox comboBoxStatus;
	private JComboBox comboBoxChannelsStatus;
	private JComboBox comboBoxChannels;
	private JTextField txtAccountNo;
	private JTextField txtStartDate;
	private JTextField txtEndDate;
	private JTextField txtOptionStartDate;
	private JTextField txtOptionEndDate;

	CableTVPanel() {
		super(null);
		this.setBackground(PresentationConstant.CONSOLE_BACKGROUND);
		this.setPreferredSize(new Dimension(1004, 643));
		initialization();

	}

	public void initialization() {
		removeAll();

		final JLabel cableTvPanelLabel = new JLabel();
		cableTvPanelLabel.setHorizontalAlignment(SwingConstants.CENTER);
		cableTvPanelLabel.setFont(new Font("", Font.BOLD, 16));
		cableTvPanelLabel.setText("Cable TV");
		cableTvPanelLabel.setBounds(0, 10, 1004, 21);
		add(cableTvPanelLabel);
		
		JLabel lblBorder = new JLabel();
		lblBorder.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
		lblBorder.setBounds(40, 71, 944, 245);
		add(lblBorder);
		
		JLabel lblMobileVoice = new JLabel("Cable TV Subscriptions");
		lblMobileVoice.setFont(new Font("Dialog", Font.BOLD, 14));
		lblMobileVoice.setBounds(90, 88, 242, 21);
		add(lblMobileVoice);
		
		JLabel lblAccountNo = new JLabel("Account No:");
		lblAccountNo.setBounds(90, 133, 106, 14);
		add(lblAccountNo);

		txtAccountNo = new JTextField();
		txtAccountNo.setColumns(10);
		txtAccountNo.setBounds(206, 130, 248, 20);
		add(txtAccountNo);
		
		btnSearch = new JButton("Search");
		btnSearch.setBounds(502, 130, 89, 23);
		btnSearch.addActionListener(this);
		add(btnSearch);
		
		JLabel lblStartDate = new JLabel("Date Commenced:");
		lblStartDate.setBounds(90, 166, 106, 14);
		add(lblStartDate);

		txtStartDate = new JTextField();
		txtStartDate.setEditable(false);
		txtStartDate.setColumns(10);
		txtStartDate.setBounds(206, 164, 248, 20);
		add(txtStartDate);
		
		JLabel lblEndDate = new JLabel("Date Terminated:");
		lblEndDate.setBounds(90, 202, 106, 14);
		add(lblEndDate);
		
		txtEndDate = new JTextField();
		txtEndDate.setEditable(false);
		txtEndDate.setColumns(10);
		txtEndDate.setBounds(206, 200, 248, 20);
		add(txtEndDate);
		
		JLabel lblStatus = new JLabel("Status:");
		lblStatus.setBounds(90, 238, 106, 14);
		add(lblStatus);

		comboBoxStatus = new JComboBox();
		comboBoxStatus.setBounds(206, 236, 137, 20);
		comboBoxStatus.addItem("");
		comboBoxStatus.addItem("Active");
		comboBoxStatus.addItem("Terminate");
		add(comboBoxStatus);

		btnUpdate = new JButton("Update / Add");
		btnUpdate.setBounds(125, 274, 106, 23);
		btnUpdate.addActionListener(this);
		add(btnUpdate);

		btnClear = new JButton("Clear");
		btnClear.setBounds(275, 274, 89, 23);
		btnClear.addActionListener(this);
		add(btnClear);
		
		
		//Extra Channel
		JLabel lblExtraChannelBorder = new JLabel();
		lblExtraChannelBorder.setBounds(40, 341, 944, 235);
		lblExtraChannelBorder.setBorder(new EtchedBorder(EtchedBorder.LOWERED));
		add(lblExtraChannelBorder);
		
		JLabel lblExtraOptions = new JLabel("Extra Channels");
		lblExtraOptions.setFont(new Font("Dialog", Font.BOLD, 14));
		lblExtraOptions.setBounds(90, 358, 242, 21);
		add(lblExtraOptions);
		
		JLabel lblOptions = new JLabel("Channel Name:");
		lblOptions.setBounds(90, 390, 106, 14);
		add(lblOptions);
		
		comboBoxChannels = new JComboBox();
		comboBoxChannels.setEnabled(false);
		comboBoxChannels.setEditable(true);
		comboBoxChannels.setBounds(206, 388, 137, 20);
		comboBoxChannels.addItem("");
		add(comboBoxChannels);

		JLabel lblOptionStatus = new JLabel("Status:");
		lblOptionStatus.setBounds(90, 426, 106, 14);
		add(lblOptionStatus);

		comboBoxChannelsStatus = new JComboBox();
		comboBoxChannelsStatus.setEnabled(false);
		comboBoxChannelsStatus.setBounds(206, 423, 137, 20);
		comboBoxChannelsStatus.addItem("");
		comboBoxChannelsStatus.addItem("Active");
		comboBoxChannelsStatus.addItem("Terminate");
		add(comboBoxChannelsStatus);
		
		JLabel lblStartDate2 = new JLabel("Date Commenced:");
		lblStartDate2.setBounds(90, 462, 106, 14);
		add(lblStartDate2);
		
		txtOptionStartDate = new JTextField();
		txtOptionStartDate.setEditable(false);
		txtOptionStartDate.setColumns(10);
		txtOptionStartDate.setBounds(206, 460, 248, 20);
		add(txtOptionStartDate);
		
		JLabel lblEndDate2 = new JLabel("Date Terminated:");
		lblEndDate2.setBounds(90, 498, 106, 14);
		add(lblEndDate2);
		
		txtOptionEndDate = new JTextField();
		txtOptionEndDate.setEditable(false);
		txtOptionEndDate.setColumns(10);
		txtOptionEndDate.setBounds(206, 496, 248, 20);
		add(txtOptionEndDate);
		
		btnTransfer = new JButton("Update / Add");
		btnTransfer.setEnabled(false);
		btnTransfer.setBounds(125, 534, 106, 23);
		btnTransfer.addActionListener(this);
		add(btnTransfer);
		
		comboBoxChannels.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent itemEvent) {
				popupExtraChannel();
			}
		});
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	public void actionPerformed(ActionEvent ae) {
		if (ae.getSource() == btnClear) {
			clear();			
		} else if (ae.getSource() == btnSearch) {
			if (StringUtil.isBlank(txtAccountNo.getText())) {
				JOptionPane.showMessageDialog(this, "Account No Required.", "Please enter Account No", JOptionPane.ERROR_MESSAGE);
			}else{
				String accountNo = txtAccountNo.getText().trim().toUpperCase();
				ArrayList<Subscription> subscriptionList = ApplicationFacade.getInstance().getSubscription(accountNo);
				if(null != subscriptionList){
					CableTV cableTv = null;
					for(Subscription sub: subscriptionList){
						if(sub instanceof CableTV){
							cableTv = (CableTV)sub;
							break;
						}
					}
					
					if(null != cableTv){
						clear();
						
						txtAccountNo.setText(accountNo);
						if(null != cableTv.getStartDate()){
							txtStartDate.setText(DateUtil.formatDate(cableTv.getStartDate(), DateUtil.DATE_TIME_FORMAT));
						}
						if(null != cableTv.getEndDate()){
							txtEndDate.setText(DateUtil.formatDate(cableTv.getEndDate(), DateUtil.DATE_TIME_FORMAT));
						}
						if(cableTv.getStatus()){
							comboBoxStatus.setSelectedIndex(1);
						}else{
							comboBoxStatus.setSelectedIndex(2);
						}
						
						ArrayList<CableTVChannel> cableTvChannels = cableTv.getChannels();
						if(null != cableTvChannels){
							for(CableTVChannel extra: cableTvChannels){
								if(StringUtil.isNotBlank(extra.getChannelName())){
									comboBoxChannels.addItem(extra.getChannelName());
								}
							}
						}

						btnSearch.setEnabled(false);
						txtAccountNo.setEditable(false);
						btnTransfer.setEnabled(true);
						comboBoxChannels.setEnabled(true);
						comboBoxChannelsStatus.setEnabled(true);
					}
					else {
						JOptionPane.showMessageDialog(this, "No existing Cable TV Subscription",
								"No subscription", JOptionPane.ERROR_MESSAGE);
					}
				}
				else {
					JOptionPane.showMessageDialog(this, "No existing Cable TV Subscription",
							"No subscription", JOptionPane.ERROR_MESSAGE);
				}
			}
		} else if (ae.getSource() == btnUpdate) {
			String errMsg = "";
			if(StringUtil.isBlank(txtAccountNo.getText())){
				errMsg += "Account No is required.\n";
			}else if(null == ApplicationFacade.getInstance().getCustomerByAccountNo(txtAccountNo.getText())){
				errMsg += "Account No cannot be found.\n";
			}
			
			if(StringUtil.isNotEmpty(errMsg)){
				JOptionPane.showMessageDialog(this, errMsg,	"Error Message", JOptionPane.ERROR_MESSAGE);
			}else{
				boolean isNew = true;
				String accountNo = txtAccountNo.getText().trim().toUpperCase();
				CableTV cableTV = getCableTVByAccountNo(accountNo);
				
				if(null == cableTV){
					cableTV = new CableTV(new Date(), null, true);
					cableTV.addChannel("DummyChannel1", new CableTVChannel());
					cableTV.addChannel("DummyChannel2", new CableTVChannel());
					cableTV.addChannel("DummyChannel3", new CableTVChannel());
					ApplicationFacade.getInstance().addSubscription(accountNo, cableTV);
				}else{
					isNew = false;
					
					if(comboBoxStatus.getSelectedIndex() == 2){
						cableTV.setStatus(false);
						cableTV.setEndDate(new Date());
					}else{
						cableTV.setStatus(true);
						cableTV.setEndDate(null);
					}
				}
				
				if(null != cableTV.getStartDate()){
					txtStartDate.setText(DateUtil.formatDate(cableTV.getStartDate(), DateUtil.DATE_TIME_FORMAT));
				}
				if(null != cableTV.getEndDate()){
					txtEndDate.setText(DateUtil.formatDate(cableTV.getEndDate(), DateUtil.DATE_TIME_FORMAT));
				}else{
					txtEndDate.setText("");
				}
				if(cableTV.getStatus()){
					comboBoxStatus.setSelectedIndex(1);
				}else{
					comboBoxStatus.setSelectedIndex(2);
				}
				
				if(isNew){
					btnTransfer.setEnabled(true);
					comboBoxChannels.setEnabled(true);
					comboBoxChannelsStatus.setEnabled(true);
					
					JOptionPane.showMessageDialog(this, "Cable TV Subscription is created successfully.",
						"Successful Message",
						JOptionPane.INFORMATION_MESSAGE);
				}else{
					JOptionPane.showMessageDialog(this, "Cable TV Subscription is updated successfully.",
							"Successful Message",
							JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}else if(ae.getSource() == btnTransfer){
			String errMsg = "";
			
			if(StringUtil.isBlank(txtAccountNo.getText())){
				errMsg += "Account No is required.\n";
			}else if(null == ApplicationFacade.getInstance().getCustomerByAccountNo(txtAccountNo.getText())){
				errMsg += "Account No cannot be found.\n";
			}
			
			String channelName = ((String)comboBoxChannels.getSelectedItem()).trim();
			if(StringUtil.isEmpty(channelName)){
				errMsg += "Channel Name is required.";
			}
			
			if(StringUtil.isNotEmpty(errMsg)){
				JOptionPane.showMessageDialog(this, errMsg,	"Error Message", JOptionPane.ERROR_MESSAGE);
			}else{
				String accountNo = txtAccountNo.getText().trim();
				CableTV cableTV = getCableTVByAccountNo(accountNo);
				
				boolean isNew = true;
				CableTVChannel extraChannel = null;
				if(cableTV.getMapOfCableTVChannels().containsKey(channelName)){
					extraChannel = cableTV.getMapOfCableTVChannels().get(channelName);
					isNew = false;
					
					if(comboBoxChannelsStatus.getSelectedIndex() == 2){
						extraChannel.setActiveStatus(false);
						extraChannel.setEndDate(new Date());
					}else{
						extraChannel.setActiveStatus(true);
						extraChannel.setEndDate(null);
					}
				}else{
					ApplicationFacade.getInstance().addExtraCableTVChannels(channelName, new Date(), null, cableTV);
					extraChannel = cableTV.getMapOfCableTVChannels().get(channelName);
				}
				
				if(extraChannel.isActiveStatus()){
					comboBoxChannelsStatus.setSelectedIndex(1);
				}else{
					comboBoxChannelsStatus.setSelectedIndex(2);
				}
				if(null != extraChannel.getStartDate()){
					txtOptionStartDate.setText(DateUtil.formatDate(extraChannel.getStartDate(), DateUtil.DATE_TIME_FORMAT));
				}
				if(null != extraChannel.getEndDate()){
					txtOptionEndDate.setText(DateUtil.formatDate(extraChannel.getEndDate(), DateUtil.DATE_TIME_FORMAT));
				}else{
					txtOptionEndDate.setText("");
				}
				
				if(isNew){
					comboBoxChannels.addItem(channelName);
					comboBoxChannels.setSelectedItem(channelName);
					
					JOptionPane.showMessageDialog(this, "Extra Channel is created successfully.",
						"Successful Message",
						JOptionPane.INFORMATION_MESSAGE);
				}else{
					JOptionPane.showMessageDialog(this, "Extra Channel is updated successfully.",
							"Successful Message",
							JOptionPane.INFORMATION_MESSAGE);
				}
			}
		}
	}
	
	private void popupExtraChannel(){
		if(comboBoxChannels.getSelectedIndex() > 0){
			String accountNo = txtAccountNo.getText().trim();
			CableTV cableTV = getCableTVByAccountNo(accountNo);
			
			if(null != cableTV){
				CableTVChannel cableTVChannel = cableTV.getMapOfCableTVChannels().get(comboBoxChannels.getSelectedItem());
				if(cableTVChannel.isActiveStatus()){
					comboBoxChannelsStatus.setSelectedIndex(1);
				}else{
					comboBoxChannelsStatus.setSelectedIndex(2);
				}
				
				if(null != cableTVChannel.getStartDate()){
					txtOptionStartDate.setText(DateUtil.formatDate(cableTVChannel.getStartDate(), DateUtil.DATE_TIME_FORMAT));
				}else{
					txtOptionStartDate.setText("");
				}
				
				if(null != cableTVChannel.getEndDate()){
					txtOptionEndDate.setText(DateUtil.formatDate(cableTVChannel.getEndDate(), DateUtil.DATE_TIME_FORMAT));
				}else{
					txtOptionEndDate.setText("");
				}
			}else{
				comboBoxChannelsStatus.setSelectedIndex(0);
				txtOptionStartDate.setText("");
				txtOptionEndDate.setText("");
			}
		}else{
			comboBoxChannelsStatus.setSelectedIndex(0);
			txtOptionStartDate.setText("");
			txtOptionEndDate.setText("");
		}
	}
	
	private CableTV getCableTVByAccountNo(String accountNo){
		CableTV cableTV = null;
		
		ArrayList<Subscription> subscriptionList = ApplicationFacade.getInstance().getSubscription(accountNo);
		if(null != subscriptionList){
			for(Subscription sub: subscriptionList){
				if(sub instanceof CableTV){
					cableTV = (CableTV)sub;
					break;
				}
			}
		}
		
		return cableTV;
	}
	
	public void clear() {
		btnSearch.setEnabled(true);
		txtAccountNo.setEditable(true);
		btnTransfer.setEnabled(false);
		comboBoxChannels.setEnabled(false);
		comboBoxChannelsStatus.setEnabled(false);
		
		comboBoxStatus.setSelectedIndex(0);
		comboBoxChannelsStatus.setSelectedIndex(0);
		
		comboBoxChannels.removeAllItems();
		comboBoxChannels.addItem("");
		comboBoxChannels.setSelectedIndex(0);
		
		txtAccountNo.setText("");
		txtStartDate.setText("");
		txtEndDate.setText("");
		txtOptionStartDate.setText("");
		txtOptionEndDate.setText("");
	}
	
	public static CableTVPanel getInstance() {
		synchronized (CableTVPanel.class) {
			if (INSTANCE == null) {
				INSTANCE = new CableTVPanel();
			}
			return INSTANCE;
		}
	}
}
